<?php
/**
 * 请求分发重定向处理类.
 *
 * 通过该类进行请求的分发以及重定向,请求分发有三种分发类型:'重定向类型','重定向到新的action处理操作','视图渲染'.
 *
 * @author Qiong Wu <papa0924@gmail.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.windframework.com
 *
 * @version $Id: WindDispatcher.php 3904 2013-01-08 07:01:26Z yishuo $
 */
class WindDispatcher extends WindModule
{
    /**
     * 存储请求的队列信息.
     *
     * @var array
     */
    protected $maxForwrd = array();
    protected $display = false;

    /**
     * @param WindForward $forward
     * @param WindRouter  $router
     * @param bool        $display
     */
    public function dispatch($forward, $router, $display)
    {
        if ($forward->getIsRedirect()) {
            $this->dispatchWithRedirect($forward, $router);
        } elseif ($forward->getIsReAction()) {
            if (count($this->maxForwrd) > 10) {
                throw new WindFinalException(
                    '[web.WindDispatcher.dispatch] more than 10 times forward request. ('.implode(', ',
                        $this->maxForwrd).')');
            }
            $token = $router->getModule().'/'.$router->getController().'/'.$router->getAction();
            array_push($this->maxForwrd, $token);
            $this->dispatchWithAction($forward, $router, $display);
        } else {
            $view = $forward->getWindView();
            if ($view->templateName) {
                $this->getResponse()->setData($forward->getVars(), $view->templateName);
                $view->render($this->display || $display);
            }
            $this->display = false;
        }
    }

    /**
     * 重定向请求到新的url地址
     *
     * 重定向请求到新的url地址是通过head方式重新开启一个url访问请求.
     *
     * @param WindForward        $forward
     * @param AbstractWindRouter $router
     */
    protected function dispatchWithRedirect($forward, $router)
    {
        if (!($_url = $forward->getUrl())) {
            $_url = $router->assemble($forward->getAction(), $forward->getArgs());
        }
        $_url = WindUrlHelper::checkUrl($_url, true);
        $this->getResponse()->sendRedirect($_url);
    }

    /**
     * 重定向请求到新的action操作.
     *
     * 该种重定向类型,是中断当前的请求执行过程,开启另外的action操作处理.是在一次请求内部进行重定向,
     * 所以之前的一些处理的结果变量,在重定向后是会继续存在,并可通过forward变量进行访问的.也就是不仅仅是过程的重定向,
     * 也是状态的重定向.
     *
     * @param WindForward $forward
     * @param WindRouter  $router
     * @param bool        $display
     */
    protected function dispatchWithAction($forward, $router, $display)
    {
        if (!$action = $forward->getAction()) {
            throw new WindException('[web.WindDispatcher.dispatchWithAction] forward fail.',
                WindException::ERROR_PARAMETER_TYPE_ERROR);
        }
        $this->display = $display;
        list($_a, $_c, $_m, $arg) = WindUrlHelper::resolveAction($action);
        foreach ($arg as $key => $value) {
            $_GET[$key] = $value;
        }
        foreach ($forward->getArgs() as $key => $value) {
            $_POST[$key] = $value;
        }

        $_a && $router->setAction($_a);
        $_c && $router->setController($_c);
        $_m && $router->setModule($_m);
        Wind::getApp()->run();
    }
}
